#include "config.h"

#include "lib/libbase/libbase.h"

static ecm_uint32	scenario;
static ECMBOOL		child_mode;
static char		*progname;

static void
usage(void)
{
	printf(
"Usage: process_test <options> [<scenario #>]\n"
" Options:\n"
"   -c: child mode\n"
"   -h: this message\n"
" Scenario #:\n"
	);
}

static void
parse_args(int argc, char *argv[])
{
	int	c;

	while ((c = ecm_getopt(argc, argv, "ch")) != -1) {
		switch(c) {
		case 'h':
			usage();
			ecm_exit(0);
			break;
		case 'c':
			child_mode = ECM_TRUE;
			break;
		default:
			usage();
			ecm_exit(1);
			break;
		}
	}

	if (argc > ecm_optind) {
		if (ecm_sscanf(argv[ecm_optind], "%u", &scenario) != 1) {
			usage();
			ecm_exit(1);
		}
	}
}

static void
run_process_dummy(void)
{
	ecm_exectx_t	ctx;

	ecm_test_start("ecm_init_exectx/ecm_clear_exectx");
	ecm_init_exectx(&ctx);
	ecm_clear_exectx(&ctx);
	ecm_test_ok();
}

static void
run_process_1sec_sleep_nowait(void)
{
	ecm_exectx_t	ctx;
	ecm_err_t	err;
	char	*command;

	ecm_test_start("exec 1sec sleep and DO NOT wait");
	ecm_init_exectx(&ctx);

	ecm_asprintf(&command, "%s -c 1", progname);
	ctx.command = command;

	if ((err = ecm_exec_process(&ctx, NULL, NULL)) != ECM_OK)
		ecm_test_failed("exec failed: %d", err);

	ecm_clear_exectx(&ctx);
	ecm_free(command);

	ecm_test_ok();
}

static void
run_process_1sec_sleep(void)
{
	ecm_exectx_t	ctx;
	ecm_err_t	err;
	char	*command;

	ecm_test_start("exec 1sec sleep and WAIT");
	ecm_init_exectx(&ctx);

	ecm_asprintf(&command, "%s -c 1", progname);
	ctx.command = command;

	if ((err = ecm_exec_process(&ctx, NULL, NULL)) != ECM_OK)
		ecm_test_failed("exec failed: %d", err);

	if ((err = ecm_wait_process(&ctx, 500)) != -ERR_ECM_AGAIN)
		ecm_test_failed("0.5sec wait failed: %d", err);

	if ((err = ecm_wait_process(&ctx, 1500)) != ECM_OK)
		ecm_test_failed("wait failed: %d", err);

	ecm_clear_exectx(&ctx);
	ecm_free(command);

	ecm_test_ok();
}

static void
read_fd(int fd)
{
	char	buf[4096];
	ecm_size_t	size;

	while (ECM_TRUE) {
		size = 4096;
		if (!ecm_read(fd, buf, &size) || size == 0)
			break;
	}
}

static void
run_process_output_reading(void)
{
	ecm_exectx_t	ctx;
	ecm_err_t	err;
	int	fd_in;
	char	*command;

	ecm_test_start("exec output reader");
	ecm_init_exectx(&ctx);

	ecm_asprintf(&command, "%s -c 2", progname);
	ctx.command = command;

	if ((err = ecm_exec_process(&ctx, &fd_in, NULL)) != ECM_OK)
		ecm_test_failed("exec failed: %d", err);

	read_fd(fd_in);

	if ((err = ecm_wait_process(&ctx, 1000)) != ECM_OK)
		ecm_test_failed("wait failed: %d", err);

	ecm_clear_exectx(&ctx);
	ecm_free(command);

	ecm_test_ok();
}

static int
sleep_1sec(void)
{
	ecm_sleep(1000);
	return 0;
}

static int
dump_message(void)
{
	printf("dump message");
	ecm_sleep(300);
	printf("dump messgge again");
	ecm_sleep(300);
	printf("dump message done");

	return 0;
}

static int
run_child_mode()
{
	switch (scenario) {
	case 1:
		return sleep_1sec();
	case 2:
		return dump_message();
	default:
		return 1;
	}
}

int
main(int argc, char *argv[])
{
	ecm_initialize();

	parse_args(argc, argv);
	progname = ecm_get_progname();

	if (child_mode)
		return run_child_mode();

	switch (scenario) {
	default:
		run_process_dummy();
		run_process_1sec_sleep_nowait();
		run_process_1sec_sleep();
		run_process_output_reading();
		break;
	}

	return 0;
}

